#!/usr/bin/env node
import fs from 'fs'
import path from 'path'
import tinify from 'tinify'
import ProgressBar from 'progress'
import chalk from 'chalk'
import { program } from 'commander'

const API_KEY_PATH = path.join(process.env.HOME || process.env.USERPROFILE || '', '.tiny')
const IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.webp']

/**
 * 读取 API 密钥文件内容
 * @param apiKeyPath - API 密钥文件路径
 * @returns 返回读取到的 API 密钥字符串
 * @throws 如果文件不存在，输出错误信息并退出程序
 */
function readApiKey(apiKeyPath: string): string {
    if (!fs.existsSync(apiKeyPath)) {
        console.error(chalk.red('错误: 未找到 ~/.tiny 文件，请确保该文件存在并包含有效的 TINY API KEY。'))
        process.exit(1)
    }
    return fs.readFileSync(apiKeyPath, 'utf-8').trim()
}

/**
 * 获取指定目录下的所有图片文件
 * @param directory - 要搜索的目录路径
 * @returns 返回符合条件的图片文件路径数组
 */
function getImageFiles(directory: string): string[] {
    const files = fs.readdirSync(directory)
    return files.filter((file) => IMAGE_EXTENSIONS.includes(path.extname(file).toLowerCase()))
}

/**
 * 压缩指定图片文件
 * @param file - 要压缩的图片文件路径
 * @param bar - 进度条对象，用于更新压缩进度
 * @returns 无返回值
 */
async function compressImage(file: string, bar: ProgressBar): Promise<void> {
    try {
        const source = tinify.fromFile(file)
        await source.toFile(file)
        console.log(chalk.green(`成功压缩: ${file} \n`))
    } catch (err: any) {
        console.error(chalk.yellow(`压缩 ${file} 失败:`), err.message)
    } finally {
        bar.tick()
    }
}

/**
 * 主函数，负责读取 API 密钥、获取图片文件并压缩图片
 * @returns 无返回值
 */
async function main() {
    program
        .name('tiny')
        .description('CLI tool to compress images using TinyPNG API')
        .version('1.0.0')
        .argument('[directory]', 'directory containing images to compress', process.cwd())
        .parse()

    const apiKey = readApiKey(API_KEY_PATH)
    if (!/^[a-zA-Z0-9]{32}$/.test(apiKey)) {
        console.error(chalk.red('错误: API 密钥格式无效，应为32位字母数字组合'))
        process.exit(1)
    }
    tinify.key = apiKey

    const directory = program.args[0]
    const imageFiles = getImageFiles(directory)
    if (imageFiles.length === 0) {
        console.log(chalk.blue('没有找到可压缩的图片文件'))
        process.exit(0)
    }

    const bar = new ProgressBar('压缩进度 [:bar] :percent :etas', {
        complete: '=',
        incomplete: ' ',
        width: 40,
        total: imageFiles.length,
    })

    for (const file of imageFiles) {
        await compressImage(file, bar)
    }

    console.log(chalk.green('所有图片压缩完成'))
}

main().catch((err) => {
    console.error(chalk.red('程序运行出错:'), err.message)
    process.exit(1)
})
